/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <gtest/gtest.h>
#include <internal/chip/chip_base/chip.h>
#include <internal/bus/bus_base/bus.h>
#include <internal/hasdef.h>
#include <mc/dict.h>
#include <memory>
#include <vector>
#include <string>

#include "../test_utils/mock_bus.h"

namespace {

// Mock bus for testing
class test_bus : public dev::bus_base {
public:
    test_bus() = default;
    ~test_bus() override = default;

    uint32_t read(ACCESS_DATA_S& input) override {
        ++m_read_call_count;
        m_last_access = input;
        if (!m_read_payloads.empty()) {
            input.out_buffer = m_read_payloads.front();
            m_read_payloads.erase(m_read_payloads.begin());
        } else {
            input.out_buffer.clear();
        }
        return m_read_result;
    }

    uint32_t write(ACCESS_DATA_S& input) override {
        ++m_write_call_count;
        m_last_access = input;
        return m_write_result;
    }

    uint8_t get_id() override {
        return m_id;
    }

    void bus_lock() override {
        ++m_lock_call_count;
    }

    void bus_unlock() override {
        ++m_unlock_call_count;
    }

    void set_id(uint8_t id) {
        m_id = id;
    }

    void set_read_result(int32_t result) {
        m_read_result = result;
    }

    void set_write_result(int32_t result) {
        m_write_result = result;
    }

    void add_read_payload(const std::vector<uint8_t>& payload) {
        m_read_payloads.push_back(payload);
    }

    ACCESS_DATA_S m_last_access{};
    int m_read_call_count = 0;
    int m_write_call_count = 0;
    int m_lock_call_count = 0;
    int m_unlock_call_count = 0;

private:
    uint8_t m_id = 0;
    int32_t m_read_result = HAS_OK;
    int32_t m_write_result = HAS_OK;
    std::vector<std::vector<uint8_t>> m_read_payloads;
};

class chip_base_test : public ::testing::Test {
protected:
    void SetUp() override {
        m_bus = std::make_shared<test_bus>();
        m_bus->set_id(1);
        m_chip = std::make_shared<dev::chip_base>();
    }

    void TearDown() override {
    }

    std::shared_ptr<test_bus> m_bus;
    std::shared_ptr<dev::chip_base> m_chip;
};

// 测试构造函数和析构函数
TEST_F(chip_base_test, constructor_and_destructor) {
    dev::chip_base chip;
    EXPECT_EQ(chip.get_left_chip(), nullptr);
    EXPECT_EQ(chip.get_left_bus(), nullptr);
    EXPECT_EQ(chip.get_host_bus(), nullptr);
}

// 测试 init 成功
TEST_F(chip_base_test, init_success) {
    mc::mutable_dict csr_object;
    csr_object["Address"] = static_cast<uint32_t>(0x70);
    csr_object["OffsetWidth"] = static_cast<uint8_t>(1);
    csr_object["AddrWidth"] = static_cast<uint8_t>(1);
    csr_object["WriteTmout"] = static_cast<uint32_t>(100);
    csr_object["ReadTmout"] = static_cast<uint32_t>(100);

    EXPECT_TRUE(m_chip->init(csr_object));
}

// 测试 init 部分字段
TEST_F(chip_base_test, init_partial_fields) {
    mc::mutable_dict csr_object;
    csr_object["Address"] = static_cast<uint32_t>(0x70);

    EXPECT_TRUE(m_chip->init(csr_object));
}

// 测试 init 空字典
TEST_F(chip_base_test, init_empty_dict) {
    mc::mutable_dict csr_object;
    EXPECT_TRUE(m_chip->init(csr_object));
}

// 测试 init 异常处理
TEST_F(chip_base_test, init_exception) {
    mc::mutable_dict csr_object;
    csr_object["Address"] = std::string("invalid");  // 无效类型

    EXPECT_FALSE(m_chip->init(csr_object));
}

// 测试 set_left_chip 和 get_left_chip
TEST_F(chip_base_test, set_and_get_left_chip) {
    auto left_chip = std::make_shared<dev::chip_base>();
    m_chip->set_left_chip(left_chip);
    
    auto retrieved_chip = m_chip->get_left_chip();
    EXPECT_NE(retrieved_chip, nullptr);
    EXPECT_EQ(retrieved_chip, left_chip);
}

// 测试 set_left_bus 和 get_left_bus
TEST_F(chip_base_test, set_and_get_left_bus) {
    m_chip->set_left_bus(m_bus);
    
    auto retrieved_bus = m_chip->get_left_bus();
    EXPECT_NE(retrieved_bus, nullptr);
    EXPECT_EQ(retrieved_bus, m_bus);
}

// 测试 set_host_bus 和 get_host_bus
TEST_F(chip_base_test, set_and_get_host_bus) {
    m_chip->set_host_bus(m_bus);
    
    auto retrieved_bus = m_chip->get_host_bus();
    EXPECT_NE(retrieved_bus, nullptr);
    EXPECT_EQ(retrieved_bus, m_bus);
}

// 测试 chip_init
TEST_F(chip_base_test, chip_init) {
    int32_t ret = m_chip->chip_init();
    EXPECT_EQ(ret, HAS_OK);
}

// 测试 chip_test
TEST_F(chip_base_test, chip_test) {
    uint32_t result = 0;
    int32_t ret = m_chip->chip_test(&result);
    EXPECT_EQ(ret, HAS_OK);
}

// 测试 chip_reset
TEST_F(chip_base_test, chip_reset) {
    int32_t ret = m_chip->chip_reset();
    EXPECT_EQ(ret, HAS_OK);
}

// 测试 open_channel
TEST_F(chip_base_test, open_channel) {
    int32_t ret = m_chip->open_channel(m_bus);
    EXPECT_EQ(ret, HAS_OK);
}

// 注意：output_to_input、pack_access_data、input、output、data_access 是 protected 方法，无法直接测试
// 可以通过 bit_read、bit_write、block_read、block_write、plugin_request 等公共方法间接测试

// 测试 bit_read 成功
TEST_F(chip_base_test, bit_read_success) {
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);
    m_bus->set_read_result(HAS_OK);

    std::vector<uint8_t> read_data = {0x01, 0x02};
    m_bus->add_read_payload(read_data);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t ret = m_chip->bit_read(0x10, 2, 0xFF, in_buffer, out_buffer, error);
    EXPECT_EQ(ret, HAS_OK);
    EXPECT_TRUE(error.empty());
}

// 测试 bit_read 无 bus
TEST_F(chip_base_test, bit_read_no_bus) {
    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    EXPECT_THROW(m_chip->bit_read(0x10, 2, 0xFF, in_buffer, out_buffer, error), mc::invalid_op_exception);
}

// 测试 bit_write 成功
TEST_F(chip_base_test, bit_write_success) {
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);
    m_bus->set_write_result(HAS_OK);

    std::vector<uint8_t> in_buffer = {0x01, 0x02};
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t ret = m_chip->bit_write(0x10, 2, 0xFF, in_buffer, out_buffer, error);
    EXPECT_EQ(ret, HAS_OK);
    EXPECT_TRUE(error.empty());
}

// 测试 bit_write 无 bus
TEST_F(chip_base_test, bit_write_no_bus) {
    std::vector<uint8_t> in_buffer = {0x01, 0x02};
    std::vector<uint8_t> out_buffer;
    std::string error;

    EXPECT_THROW(m_chip->bit_write(0x10, 2, 0xFF, in_buffer, out_buffer, error), mc::invalid_op_exception);
}

// 测试 block_read 成功
TEST_F(chip_base_test, block_read_success) {
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);
    m_bus->set_read_result(HAS_OK);

    std::vector<uint8_t> read_data = {0x01, 0x02, 0x03};
    m_bus->add_read_payload(read_data);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t ret = m_chip->block_read(0x10, 3, in_buffer, out_buffer, error);
    EXPECT_EQ(ret, HAS_OK);
    EXPECT_TRUE(error.empty());
    EXPECT_EQ(out_buffer.size(), 3);
}

// 测试 block_read 无 bus
TEST_F(chip_base_test, block_read_no_bus) {
    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    EXPECT_THROW(m_chip->block_read(0x10, 3, in_buffer, out_buffer, error), mc::invalid_op_exception);
}

// 测试 block_write 成功
TEST_F(chip_base_test, block_write_success) {
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);
    m_bus->set_write_result(HAS_OK);

    std::vector<uint8_t> in_buffer = {0x01, 0x02, 0x03};
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t ret = m_chip->block_write(0x10, in_buffer, out_buffer, error);
    EXPECT_EQ(ret, HAS_OK);
    EXPECT_TRUE(error.empty());
}

// 测试 block_write 无 bus
TEST_F(chip_base_test, block_write_no_bus) {
    std::vector<uint8_t> in_buffer = {0x01, 0x02};
    std::vector<uint8_t> out_buffer;
    std::string error;

    EXPECT_THROW(m_chip->block_write(0x10, in_buffer, out_buffer, error), mc::invalid_op_exception);
}

// 测试 block_write_read 成功
TEST_F(chip_base_test, block_write_read_success) {
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);
    m_bus->set_read_result(HAS_OK);
    m_bus->set_write_result(HAS_OK);

    std::vector<uint8_t> read_data = {0x01, 0x02};
    m_bus->add_read_payload(read_data);

    std::vector<uint8_t> indata = {0xAA, 0xBB};
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t ret = m_chip->block_write_read(0x10, indata, 2, out_buffer, error);
    EXPECT_EQ(ret, HAS_OK);
    EXPECT_TRUE(error.empty());
}

// 测试 combo_block_write_read 成功
TEST_F(chip_base_test, combo_block_write_read_success) {
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);
    m_bus->set_read_result(HAS_OK);
    m_bus->set_write_result(HAS_OK);

    std::vector<uint8_t> read_data = {0x01, 0x02};
    m_bus->add_read_payload(read_data);

    std::vector<uint8_t> write_buffer = {0xAA};
    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t ret = m_chip->combo_block_write_read(0x10, write_buffer, 0x20, 2, in_buffer, out_buffer, error);
    EXPECT_EQ(ret, HAS_OK);
    EXPECT_TRUE(error.empty());
}

// 测试 combo_block_write_read 写入失败
TEST_F(chip_base_test, combo_block_write_read_write_failure) {
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);
    m_bus->set_write_result(HAS_ERR);

    std::vector<uint8_t> write_buffer = {0xAA};
    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t ret = m_chip->combo_block_write_read(0x10, write_buffer, 0x20, 2, in_buffer, out_buffer, error);
    EXPECT_EQ(ret, HAS_ERR);
    EXPECT_FALSE(error.empty());
}

// 测试多次 init
TEST_F(chip_base_test, init_multiple_times) {
    mc::mutable_dict csr_object1;
    csr_object1["Address"] = static_cast<uint32_t>(0x70);
    EXPECT_TRUE(m_chip->init(csr_object1));

    mc::mutable_dict csr_object2;
    csr_object2["Address"] = static_cast<uint32_t>(0x71);
    EXPECT_TRUE(m_chip->init(csr_object2));
}

// 测试 plugin_request 成功
TEST_F(chip_base_test, plugin_request_success) {
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);
    m_bus->set_read_result(HAS_OK);
    m_bus->set_write_result(HAS_OK);

    std::vector<uint8_t> read_data(129, 0x01);  // PLUGIN_REQUEST_READ_LENGTH = 129
    m_bus->add_read_payload(read_data);

    std::vector<uint8_t> params = {0xAA, 0xBB};
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t ret = m_chip->plugin_request("test_plugin", "test_cmd", params, out_buffer, error);
    EXPECT_EQ(ret, HAS_OK);
    EXPECT_TRUE(error.empty());
}

// 测试 plugin_request 无 bus
TEST_F(chip_base_test, plugin_request_no_bus) {
    std::vector<uint8_t> params = {0xAA};
    std::vector<uint8_t> out_buffer;
    std::string error;

    EXPECT_THROW(m_chip->plugin_request("test_plugin", "test_cmd", params, out_buffer, error), mc::invalid_op_exception);
}

// 测试 plugin_request 写入失败
TEST_F(chip_base_test, plugin_request_write_failure) {
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);
    m_bus->set_write_result(HAS_ERR);

    std::vector<uint8_t> params = {0xAA};
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t ret = m_chip->plugin_request("test_plugin", "test_cmd", params, out_buffer, error);
    EXPECT_EQ(ret, HAS_ERR);
    EXPECT_FALSE(error.empty());
}

// 测试 plugin_request 读取失败
TEST_F(chip_base_test, plugin_request_read_failure) {
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);
    m_bus->set_write_result(HAS_OK);
    m_bus->set_read_result(HAS_ERR);

    std::vector<uint8_t> params = {0xAA};
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t ret = m_chip->plugin_request("test_plugin", "test_cmd", params, out_buffer, error);
    EXPECT_EQ(ret, HAS_ERR);
    EXPECT_FALSE(error.empty());
}

} // namespace

